package com.va.feedback;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import com.va.feedback.component.AbstractFeedback;
import com.va.feedback.component.CheckboxFeedback;
import com.va.feedback.component.RadioFeedback;
import com.va.feedback.component.RatingFeedback;
import com.va.feedback.component.TextFeedback;
import com.va.feedback.component.YesNoFeedback;
import com.va.feedback.network.ConnectionManager;

public class FeedbackDroidActivity extends Activity {
	
	private String IP = "droidfeedback.com";
	private String app_client;
	private String app_secret;
	
	private static float scale = 0f;
	private LinearLayout mainLayout;
	private Map<Integer, AbstractFeedback> questionMap = new HashMap<Integer, AbstractFeedback>();
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        scale = this.getResources().getDisplayMetrics().density;

        Intent intent = getIntent();
        app_client = intent.getStringExtra("app_client");
        app_secret = intent.getStringExtra("app_secret");
        if (app_client == null || app_secret == null) {
        	finish();
        	return;
        }
        setMainLayout();
        
        boolean isConnected = getConnevtivityStatus(); 
        if (!isConnected) {
        	finish();
        	return;
        }
        String urlAddress = "http://" + IP + "/feedback/questions/" + app_client + "/" + app_secret;
        showFeedbackForm(urlAddress);
    }

	private boolean getConnevtivityStatus() {
		ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
		
		if (!(cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected() ||
				cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()))
			return false;
		else 
			return true;
	}

	private void setMainLayout() {
		ScrollView mainView = new ScrollView(this);
		mainView.setVerticalScrollBarEnabled(true);
		
		mainLayout = new LinearLayout(this);
		LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		mainLayout.setOrientation(LinearLayout.VERTICAL);
		mainView.addView(mainLayout, mainLayoutParams);
		setContentView(mainView);
	}

	private void showFeedbackForm(final String urlAddress) {
		new AsyncTask<Void, Void, String>() {

			@Override
			protected String doInBackground(Void... params) {
				String query = null;
				String result = ConnectionManager.getInstance().getJSON(urlAddress, query);
				debug("GET REQUEST");
				debug(result);
				return result;
			}
			
			@Override
			protected void onPostExecute(String jsonString) {
				try {
					JSONArray array = new JSONArray(jsonString);
					int numQuestions = array.length();
					questionMap.clear();
					for (int i=0; i<numQuestions; i++) {
						JSONObject object = array.getJSONObject(i);
						debug(object.toString());
						int qid = object.getInt("qid");
						String question = object.getString("question");
						String ans_type = object.getString("ans_type");
						String attributes_json = object.has("attributes") ? object.getString("attributes") : null;
						addComponent(qid, question, ans_type, attributes_json);
					}
					if (numQuestions > 0)
						addSendFeedbackButton();
				} catch (JSONException e) {
					e.printStackTrace();
				}
			}
			
		}.execute();
	}

	protected void addSendFeedbackButton() {
		Button sendButton = new Button(this);
		LinearLayout.LayoutParams sendButtonParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		sendButton.setText("Send Feedback");
		sendButton.setGravity(Gravity.CENTER_HORIZONTAL);
		mainLayout.addView(sendButton, sendButtonParams);
		
		sendButton.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				String urlAddress = "http://" + IP + "/feedback/answers";
				try {
					Map<String, String> output = getAllFeedbackMap();
					String dataResult = ConnectionManager.getInstance().postData(urlAddress, output);
					JSONObject res = new JSONObject(dataResult);
					if ("success".equals(res.getString("status"))) {
						exitDroidFeedback(true);
					} else {
						exitDroidFeedback(false);
					}
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}

	protected void exitDroidFeedback(final boolean success) {
		String message = "";
		if (success)
			message += "Feedback posted successfully.";
		else
			message += "Couldn't post the feedback. Try again later.";
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(message)
		       .setCancelable(false)
		       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		                if (success)
		                	FeedbackDroidActivity.this.finish();
		           }
		       });
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	protected Map<String, String> getAllFeedbackMap() {
		Map<String, String> result = new HashMap<String, String>();
		JSONArray answers = new JSONArray();
		
		for (Integer qid : questionMap.keySet()) {
			AbstractFeedback feed = questionMap.get(qid);
			try {
				Object feedback = feed.getFeedback();
				if (feedback != null)
					answers.put(feedback);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		if (answers.length() > 0 && result != null) {
			result.put("answers", answers.toString());
			result.put("app_client", app_client);
			result.put("app_secret", app_secret);
			result.put("device_id_md5", getDeviceId());
		}
		return result;
		
	}

	protected JSONObject getAllFeedback() throws JSONException {
		JSONArray answers = new JSONArray();
		
		for (Integer qid : questionMap.keySet()) {
			AbstractFeedback feed = questionMap.get(qid);
			try {
				Object feedback = feed.getFeedback();
				if (feedback != null)
					answers.put(feedback);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		JSONObject result = getDeviceInformation();
		if (answers.length() > 0 && result != null) {
			result.put("answers", answers);
			result.put("app_client", app_client);
			result.put("app_secret", app_secret);
		}
		return result;
	}

	private JSONObject getDeviceInformation() {
		JSONObject deviceInfo = new JSONObject();
		try {
			deviceInfo.put("device_id_md5", getDeviceId());
		} catch (JSONException e) {
			e.printStackTrace();
			return null;
		}
		return deviceInfo;
	}
	
	private String getDeviceId() {
		TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		return encode(telManager.getDeviceId(), "MD5");
	}

	private String encode(String deviceId, String algo) {
		try{
			MessageDigest algorithm = MessageDigest.getInstance(algo);
			algorithm.reset();
			algorithm.update(deviceId.getBytes());
			byte messageDigest[] = algorithm.digest();
		            
			StringBuffer hexString = new StringBuffer();
			for (int i=0;i<messageDigest.length;i++) {
				hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
			}
			return hexString+"";
		}catch(NoSuchAlgorithmException nsae){
			return deviceId;
		}
	}

	protected void addComponent(int qid, String question, String ansType, String attributes_json) {
		if (ansType.equals(FeedbackItemConstants.CHECKBOX_TYPE)) {
			addCheckboxFeedback(question, qid, attributes_json);
		} else if (ansType.equals(FeedbackItemConstants.RADIO_TYPE)) {
			addRadioFeedback(question, qid, attributes_json);
		} else if (ansType.equals(FeedbackItemConstants.TEXT_TYPE)) {
			addTextFeedback(question, qid);
		} else if (ansType.equals(FeedbackItemConstants.YES_NO_TYPE)) {
			addYesNoFeedback(question, qid);
		} else if (ansType.equals(FeedbackItemConstants.RATING_TYPE)) {
			addRatingFeedback(question, qid);
		}
	}

	private void addRatingFeedback(String question, int qid) {
		RatingFeedback feed = new RatingFeedback(this);
		feed.setProperty(FeedbackItemConstants.QUESTION_ID, qid);
		feed.setProperty(FeedbackItemConstants.PROPERTY_QUESTION, question);
		LinearLayout.LayoutParams feedParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		int margin = (int) (scale * 5 + 0.5);
		feedParams.setMargins(margin, margin, margin, margin);
		mainLayout.addView(feed, feedParams);
		questionMap.put(qid, feed);
	}

	private void addCheckboxFeedback(String question, int qid, String attributes_json) {
		CheckboxFeedback feed = new CheckboxFeedback(this);
		feed.setProperty(FeedbackItemConstants.QUESTION_ID, qid);
		feed.setProperty(FeedbackItemConstants.PROPERTY_QUESTION, question);
		List<String> items = new ArrayList<String>();
		try {
			JSONArray attrs = new JSONArray(attributes_json);
			for (int i=0; i<attrs.length(); i++) {
				items.add((String) attrs.get(i));
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		feed.setProperty(FeedbackItemConstants.PROPERTY_CHECKBOX_ITEMS, items);
		LinearLayout.LayoutParams feedParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		int margin = (int) (scale * 5 + 0.5);
		feedParams.setMargins(margin, margin, margin, margin);
		mainLayout.addView(feed, feedParams);
		questionMap.put(qid, feed);
	}

	private void addRadioFeedback(String question, int qid, String attributes_json) {
		RadioFeedback feed = new RadioFeedback(this);
		feed.setProperty(FeedbackItemConstants.QUESTION_ID, qid);
		feed.setProperty(FeedbackItemConstants.PROPERTY_QUESTION, question);
		List<String> items = new ArrayList<String>();
		try {
			JSONArray attrs = new JSONArray(attributes_json);
			for (int i=0; i<attrs.length(); i++) {
				items.add((String) attrs.get(i));
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		feed.setProperty(FeedbackItemConstants.PROPERTY_RADIO_ITEMS, items);
		LinearLayout.LayoutParams feedParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		int margin = (int) (scale * 5 + 0.5);
		feedParams.setMargins(margin, margin, margin, margin);
		mainLayout.addView(feed, feedParams);
		questionMap.put(qid, feed);
	}

	private void addYesNoFeedback(String question, int qid) {
		YesNoFeedback feed = new YesNoFeedback(this);
		feed.setProperty(FeedbackItemConstants.QUESTION_ID, qid);
		feed.setProperty(FeedbackItemConstants.PROPERTY_QUESTION, question);
		feed.setProperty(FeedbackItemConstants.PROPERTY_YES_BUTTON, "Yes");
		feed.setProperty(FeedbackItemConstants.PROPERTY_NO_BUTTON, "No");
		LinearLayout.LayoutParams feedParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		int margin = (int) (scale * 5 + 0.5);
		feedParams.setMargins(margin, margin, margin, margin);
		mainLayout.addView(feed, feedParams);
		questionMap.put(qid, feed);
	}

	private void addTextFeedback(String question, int qid) {
		TextFeedback feed = new TextFeedback(this);
		feed.setProperty(FeedbackItemConstants.QUESTION_ID, qid);
		feed.setProperty(FeedbackItemConstants.PROPERTY_QUESTION, question);//"This is the question for TEXT?");
		feed.setProperty(FeedbackItemConstants.PROPERTY_TEXT_HINT, "Enter the feedback here");
		LinearLayout.LayoutParams feedParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		int margin = (int) (scale * 5 + 0.5);
		feedParams.setMargins(margin, margin, margin, margin);
		mainLayout.addView(feed, feedParams);
		questionMap.put(qid, feed);
	}
	
	/**
	 * @return Returns the scale of the screen of the device
	 */
	public static float getScale() {
		return scale;
	}
	
	private void debug(String message) {
		if (FeedbackItemConstants.DEBUG) {
			if (message != null)
				Log.d("FeedbackDroidActivity", message);
		}
	}
	
}